{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python Power Measurement Tutorial\n",
    "\n",
    "This tutorial shows how to perform a power measurement on the device.\n",
    "\n",
    "The Hailo device supports power measurement which is done via the control protocol, if an INA231 is assembled on the board.\n",
    "\n",
    "**Requirements:**\n",
    "\n",
    "* Run the notebook inside the Python virtual environment: ```source hailo_virtualenv/bin/activate```\n",
    "\n",
    "**Attention:**\n",
    "\n",
    "* These examples should run in a different process than the one that performs the actual inference.\n",
    "\n",
    "When inside the ```virtualenv```, run ``hailo tutorial`` to open a Jupyter server that contains the tutorials."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Single Power Measurement"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import time\n",
    "\n",
    "from hailo_platform import Device, DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor, MeasurementBufferIndex # noqa F401\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Initialize the hardware object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "target = Device()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When using the ``power_measurement()`` function with no parameters, the function tries to detect which Hailo-8 board is connected (evaluation board, M.2 or mPCIe) and determine the DVM accordingly (at the moment only the boards referred to in this section have INA231 assembelled and are supported). \n",
    "\n",
    "The parameter ``dvm`` (of type ``DvmTypes``) defines which DVM will be measured. The user can choose a specific DVM or choose the default DVM. The meaning of the default DVM changes according to the board or module in use. \n",
    "\n",
    "The default for the evaluation board is the sum of three DVMs: ``DvmTypes.VDD_CORE``, ``DvmTypes.MIPI_AVDD`` and ``DvmTypes.AVDD_H``. The sum of these three DVMs approximates of the total power consumption of the chip in PCIe setups. Only power can be measured using this default option, as voltage and current cannot be totaled (or calculated) this way.\n",
    "\n",
    "The default for platforms supporting current monitoring, such as M.2 and mPCIe modules, is ``DvmTypes.OVERCURRENT_PROTECTION``, which measures the power consumption of the whole module. \n",
    "\n",
    "See the API documentation for further details about the supported DVMs and measurement types.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "single_power_measurement = target.control.power_measurement()\n",
    "print('Power from single measurement: {} W'.format(single_power_measurement))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Periodic Power Measurement\n",
    "\n",
    "In the following example, a periodic power measurement is taken.\n",
    "\n",
    "A measurement index is selected. It is a member of the enum class MeasurementBufferIndex (between 0 and 3). The DVM is not given so the default DVM will be used, as explained above.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "buffer_index = MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0\n",
    "target.control.set_power_measurement(buffer_index=buffer_index)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following call to ``start_power_measurement()`` allows to configure the power sampling frequency. In this case we keep the default configuration. The API documentation provides more details. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "target.control.start_power_measurement()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Clear the old samples and statistics (min, max, average) each time the measurement is taken from the chip."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "should_clear = True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The power measurement is read every second, for 10 seconds.\n",
    "\n",
    "The firmware calculates the min, max, and average of all the values from the sensor. Note that the average calculated by the firmware is the \"average of averages\". This is the average of all values that have already been averaged by the sensor. The host then requests these values from the firmware every second by calling the ``get_power_measurement()`` function. The host can also read the average time interval between new sensor values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "for _ in range(10):\n",
    "    time.sleep(1)\n",
    "    # Get saved power measurement values from the firmware.\n",
    "    measurements = target.control.get_power_measurement(buffer_index=buffer_index, should_clear=should_clear)\n",
    "    print('Average power is {} W. Min power is {} W. Max power is {} W.\\nAverage time between power samples is {} mS\\n'.format(measurements.average_value, measurements.min_value, measurements.max_value, measurements.average_time_value_milliseconds))\n",
    "\n",
    "# Stop performing periodic power measurement\n",
    "target.control.stop_power_measurement()\n",
    "\n",
    "target.release()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
